<!DOCTYPE html>
<html>
<head>
    <title>Electromagnetic Field Diagram</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        canvas {
            border: 1px solid #ccc;
            background-color: #fff;
        }
    </style>
</head>
<body>
<canvas id="physicsCanvas" width="600" height="450"></canvas>
<script>
    const canvas = document.getElementById('physicsCanvas');
    const ctx = canvas.getContext('2d');

    // Helper function to draw an arrow
    function drawArrow(ctx, fromx, fromy, tox, toy, headlen = 10) {
        const angle = Math.atan2(toy - fromy, tox - fromx);
        ctx.beginPath();
        ctx.moveTo(fromx, fromy);
        ctx.lineTo(tox, toy);
        ctx.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
        ctx.moveTo(tox, toy);
        ctx.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
        ctx.stroke();
    }

    // Main drawing function
    function drawDiagram() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.strokeStyle = 'black';
        ctx.fillStyle = 'black';
        ctx.lineWidth = 1.5;

        // Define origin and dimensions
        const O = { x: 120, y: 225 };
        const L = 350;
        const gap_half = 70;
        const magnet_thickness = 40;

        // 1. Draw Coordinate System
        ctx.font = "italic 22px 'Times New Roman'";
        // x-axis
        drawArrow(ctx, O.x, O.y, O.x, 50);
        ctx.fillText('x', O.x - 25, 50);
        // y-axis
        drawArrow(ctx, O.x, O.y, O.x - 50, O.y + 50);
        ctx.fillText('y', O.x - 70, O.y + 55);
        // z-axis
        drawArrow(ctx, O.x, O.y, O.x + L + 80, O.y);
        ctx.fillText('z', O.x + L + 85, O.y + 8);
        // Origin label
        ctx.fillText('O', O.x - 28, O.y + 15);

        // 2. Draw Magnets
        const x_left = O.x;
        const x_right = O.x + L;
        const y_top_inner = O.y - gap_half;
        const y_top_outer = y_top_inner - magnet_thickness;
        const y_bot_inner = O.y + gap_half;
        const y_bot_outer = y_bot_inner + magnet_thickness;

        // Top Magnet
        ctx.beginPath();
        ctx.rect(x_left, y_top_outer, L, magnet_thickness);
        ctx.stroke();
        
        // Bottom Magnet
        ctx.beginPath();
        ctx.rect(x_left, y_bot_inner, L, magnet_thickness);
        ctx.stroke();

        // Magnet Labels
        ctx.font = "24px 'KaiTi', 'SimSun', sans-serif";
        ctx.textAlign = 'center';
        ctx.fillText('磁铁', O.x + L / 2, y_top_outer + 28);
        ctx.fillText('磁铁', O.x + L / 2, y_bot_inner + 30);
        ctx.textAlign = 'start'; // Reset alignment

        // 3. Draw Length L dimension line
        const L_y_pos = y_bot_outer + 40;
        ctx.beginPath();
        // line
        ctx.moveTo(x_left, L_y_pos);
        ctx.lineTo(x_right, L_y_pos);
        // left arrow head
        ctx.moveTo(x_left, L_y_pos);
        ctx.lineTo(x_left - 10, L_y_pos - 5);
        ctx.moveTo(x_left, L_y_pos);
        ctx.lineTo(x_left - 10, L_y_pos + 5);
        // right arrow head
        ctx.moveTo(x_right, L_y_pos);
        ctx.lineTo(x_right + 10, L_y_pos - 5);
        ctx.moveTo(x_right, L_y_pos);
        ctx.lineTo(x_right + 10, L_y_pos + 5);
        ctx.stroke();
        ctx.font = "italic 22px 'Times New Roman'";
        ctx.fillText('L', O.x + L / 2 - 5, L_y_pos - 8);

        // 4. Draw Magnetic Field B0
        const B_arrow_y_start = O.y + gap_half - 15;
        const B_arrow_y_end = O.y - gap_half + 15;
        // The main labeled arrow
        drawArrow(ctx, O.x + 130, B_arrow_y_start, O.x + 130, B_arrow_y_end);
        ctx.fillText('B', O.x + 145, O.y);
        ctx.font = "italic 16px 'Times New Roman'";
        ctx.fillText('0', O.x + 158, O.y + 5);
        ctx.font = "italic 22px 'Times New Roman'";
        
        // Other field lines
        drawArrow(ctx, O.x + 250, B_arrow_y_start, O.x + 250, B_arrow_y_end);
        drawArrow(ctx, O.x + 300, B_arrow_y_start, O.x + 300, B_arrow_y_end);
        
        // 5. Draw Fringing Field
        ctx.lineWidth = 1;
        // Curve 1
        const fringe_x_start = x_right + 25;
        const fringe_y_start = O.y + gap_half - 5;
        const fringe_y_end = O.y - gap_half + 5;
        ctx.beginPath();
        ctx.moveTo(fringe_x_start, fringe_y_start);
        ctx.quadraticCurveTo(fringe_x_start + 25, O.y, fringe_x_start, fringe_y_end);
        ctx.stroke();
        drawArrow(ctx, fringe_x_start+0.1, fringe_y_end-0.1, fringe_x_start, fringe_y_end, 8);
        
        // Curve 2
        const fringe_x_start2 = fringe_x_start + 15;
        ctx.beginPath();
        ctx.moveTo(fringe_x_start2, fringe_y_start);
        ctx.quadraticCurveTo(fringe_x_start2 + 25, O.y, fringe_x_start2, fringe_y_end);
        ctx.stroke();
        drawArrow(ctx, fringe_x_start2+0.1, fringe_y_end-0.1, fringe_x_start2, fringe_y_end, 8);
        ctx.lineWidth = 1.5; // Reset line width
        
        // 6. Draw Particle's Initial State
        const x0_y = O.y - 35;
        // Dot for x0
        ctx.beginPath();
        ctx.arc(O.x, x0_y, 3, 0, 2 * Math.PI);
        ctx.fill();
        ctx.fillText('x', O.x - 38, x0_y + 8);
        ctx.font = "italic 16px 'Times New Roman'";
        ctx.fillText('0', O.x - 27, x0_y + 12);
        
        // Momentum arrow p0
        ctx.font = "italic 22px 'Times New Roman'";
        drawArrow(ctx, O.x, x0_y, O.x + 100, x0_y);
        ctx.fillText('p', O.x + 105, x0_y + 8);
        ctx.font = "italic 16px 'Times New Roman'";
        ctx.fillText('0', O.x + 118, x0_y + 12);
    }

    // Call the main drawing function
    drawDiagram();
</script>
</body>
</html>